#pragma once
#include <common.hpp>

namespace sv {

	class LinSolver {
	public:
		friend class Model;
		LinSolver();
		~LinSolver();

		LinSolver(const LinSolver& solver);
		LinSolver& operator=(const LinSolver& solver);

		Var* addVars(int col, VarType type);
		const Var& getVar(int idx);
		void addConstr(const Expr& expr, ConstrOper sense, double rhs);
		void setObjective(Expr obje, int sense = MDL_MAXIMIZE);
		void print();

		double get(DoubleAttr attr);
		int get(IntAttr attr);

		rtn optimize();
	protected:

		double _simplex();
		rtn _pivot(std::pair<size_t, size_t>& p);
		rtn feasible_solution();
		void _gaussian(std::pair<size_t, size_t> p);

		Var* vars;

		matrix table;
		matrix ope_table;
		size_t cn, bn;
		std::vector<int> basic;
		rtn rtn_;
		double obj_;
		int sense;
	};

	class Model
	{
	public:
		Model();
		rtn optimize();
		
		Var* addVars(int col, VarType type);
		void addConstr(const Expr& expr, ConstrOper sense, double rhs);
		void setObjective(Expr obje, int sense = MDL_MAXIMIZE);

		double get(DoubleAttr attr);
		int get(IntAttr attr);

	private:
		LinSolver solver;
	};
}



